﻿namespace Sai.Core.Sandcastle
{
	using System.Collections.Generic;
	using System.Collections.ObjectModel;
	using System.IO;
	using Sai.Core.Reporting;

	public class Project
	{
		private ContentLayout layout = null;

		private List<string> lines = new List<string>();

		public string Folder { get; set; }

		public string Name { get; set; }

		public static Project LoadFrom(TextReader reader)
		{
			// extremely simple - not treating project file as xml or build file
			// only interested in search and replace for some files
			var projectFile = new Project();

			string input;
			while ((input = reader.ReadLine()) != null)
			{
				projectFile.lines.Add(input);
			}

			return projectFile;
		}

		public static Project LoadFrom(string path)
		{
			Project loadedProject = null;

			using (var reader = new StreamReader(path))
			{
				loadedProject = Project.LoadFrom(reader);
			}

			if (loadedProject != null)
			{
				loadedProject.Folder = path.ContainingFolder();
				loadedProject.Name = System.IO.Path.GetFileName(path);
			}

			return loadedProject;
		}

		public string ContentLayoutName
		{
			get
			{
				string layoutName = string.Empty;

				// looking for <ContentLayout Include="..." />
				foreach (var line in this.lines)
				{
					if (ProjectItem.LineMatches(line, ProjectItem.ContentLayoutTag))
					{
						ProjectItem item = new ProjectItem();
						item.Parse(line);

						if (!string.IsNullOrEmpty(this.Folder))
						{
							layoutName = item.Path.AbsoluteFromFolder(this.Folder);
						}
						else
						{
							layoutName = item.Path;
						}

						break;
					}
				}

				return layoutName;
			}
		}

		public string ContentLayoutPath
		{
			get
			{
				if (!string.IsNullOrEmpty(this.Folder))
				{
					return this.ContentLayoutName.AbsoluteFromFolder(this.Folder);
				}

				return this.ContentLayoutName;
			}
		}

		public ContentLayout ContentLayout
		{
			get
			{
				if (this.layout == null)
				{
					string baseFolder = this.Folder;
					string contentLayoutFile = this.ContentLayoutName.AbsoluteFromFolder(baseFolder);

					if (File.Exists(contentLayoutFile))
					{
						using (var reader = new StreamReader(contentLayoutFile))
						{
							this.layout = ContentLayout.LoadFrom(reader, this);
						}
					}
				}

				return this.layout;
			}
		}

		public ReadOnlyCollection<string> Content
		{
			get
			{
				List<string> content = new List<string>();

				foreach (var line in this.lines)
				{
					if (!ProjectItem.LineMatches(line, ProjectItem.ContentLayoutTag) 
						&& ProjectItem.LineMatches(line, ProjectItem.ContentTag))
					{
						ProjectItem item = new ProjectItem();
						item.Parse(line);

						if (!string.IsNullOrEmpty(this.Folder))
						{
							content.Add(item.Path.AbsoluteFromFolder(this.Folder));
						}
						else
						{
							content.Add(item.Path);
						}
					}
				}

				return new ReadOnlyCollection<string>(content);
			}
		}

		public void RemoveContent(IEnumerable<string> files)
		{
			List<string> copiedLines = new List<string>();

			foreach (var line in this.lines)
			{
				bool copyLine = true;

				if (!string.IsNullOrEmpty(line) 
					&& !ProjectItem.LineMatches(line, ProjectItem.ContentLayoutTag) 
					&& ProjectItem.LineMatches(line, ProjectItem.ContentTag))
				{
					foreach (var file in files)
					{
						string relativePath = string.IsNullOrEmpty(this.Folder) ? file : file.RelativeToFolder(this.Folder);

						if (line.Contains(relativePath))
						{
							copyLine = false;
							break;
						}
					}
				}

				if (copyLine)
				{
					copiedLines.Add(line);
				}
			}

			this.lines = copiedLines;
		}

		public void AddContent(IEnumerable<string> files)
		{
			bool firstItemGroup = true;

			List<string> copiedLines = new List<string>();

			foreach (var line in this.lines)
			{
				copiedLines.Add(line);

				if (firstItemGroup && line.Contains("<ItemGroup>"))
				{
					firstItemGroup = false;

					foreach (var file in files)
					{
						string relativePath = string.IsNullOrEmpty(this.Folder) ? file : file.RelativeToFolder(this.Folder);
						
						// trim beginning of path, matching folder
						copiedLines.Add(new ProjectItem(relativePath).ToString());
					}
				}
			}

			this.lines = copiedLines;
		}
		
		public void ReplaceContent(string topicId, ReportIndexCollection generatedFiles)
		{
			ContentLayout layout = this.ContentLayout;

			if (layout == null)
			{
				return;
			}

			TopicCollectionBuilder builder = new TopicCollectionBuilder();

			Topic topLevel = builder.Build(generatedFiles);
			layout.FindAndReplace(topicId, topLevel);
		}

		public void SaveTo(TextWriter writer)
		{
			foreach (var line in this.lines)
			{
				writer.WriteLine(line);
			}
		}

		public void SaveTo(string path)
		{
			using (var writer = new StreamWriter(path))
			{
				this.SaveTo(writer);
			}

			using (var writer = new StreamWriter(this.ContentLayoutName.AbsoluteFromFolder(this.Folder)))
			{
				this.ContentLayout.SaveTo(writer);
			}
		}
	}
}
